#include "mainwindow.h"
#include <QToolBar>
#include <QStatusBar>
#include <QMessageBox>
#include <QStyleFactory>
#include <QTimer>
#include <QDebug>
#include "qipan.h"
#include <opencv2/opencv.hpp>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), detectionWindow(nullptr)
{
    setWindowTitle("三子棋");
    setMinimumSize(600, 600);

    // 初始化电机控制器
    motorController = new MotorController("/dev/ttyS9", 115200, 10, this);
    motorController->open();
    servoController = new ServoController("/dev/ttyS5", 115200, this);
    servoController->open();

    // 创建中央部件
    QWidget *centerWidget = new QWidget(this);
    setCentralWidget(centerWidget);

    // 创建主布局
    QVBoxLayout *mainLayout = new QVBoxLayout(centerWidget);
    mainLayout->setSpacing(10);
    mainLayout->setContentsMargins(10, 10, 10, 10);

    // 创建状态标签
    statusLabel = new QLabel("游戏开始 - 玩家回合", this);
    statusLabel->setAlignment(Qt::AlignCenter);
    statusLabel->setStyleSheet("font-size: 24px; font-weight: bold; color: #333;");
    mainLayout->addWidget(statusLabel);

    // 创建棋盘
    qipan = new QiPan(this);
    mainLayout->addWidget(qipan, 1);

    // 创建控制面板
    QHBoxLayout *controlLayout = new QHBoxLayout();

    // 玩家角色选择
    QLabel *roleLabel = new QLabel("玩家棋子:", this);
    playerRoleCombo = new QComboBox(this);
    playerRoleCombo->addItem("X (先手)", PLAYER);
    playerRoleCombo->addItem("O (后手)", COMPUTER);
    playerRoleCombo->setCurrentIndex(0);

    // AI难度选择
    QLabel *aiLabel = new QLabel("AI难度:", this);
    aiDifficultyCombo = new QComboBox(this);
    aiDifficultyCombo->addItem("简单");
    aiDifficultyCombo->addItem("中等");
    aiDifficultyCombo->addItem("困难");
    aiDifficultyCombo->setCurrentIndex(1);

    // 悔棋按钮
    regretButton = new QPushButton("悔棋", this);
    regretButton->setFixedSize(80, 40);
    regretButton->setStyleSheet(
        "QPushButton {"
        "   background-color: #2196F3;"
        "   color: white;"
        "   border-radius: 5px;"
        "   font-size: 14px;"
        "}"
        "QPushButton:disabled {"
        "   background-color: #BBDEFB;"
        "}"
    );

    // 重新开始按钮
    resetButton = new QPushButton("重新开始", this);
    resetButton->setFixedSize(120, 40);
    resetButton->setStyleSheet(
        "QPushButton {"
        "   background-color: #4CAF50;"
        "   color: white;"
        "   border-radius: 5px;"
        "   font-size: 16px;"
        "}"
    );

    // 检测棋盘按钮
    detectionButton = new QPushButton("检测棋盘", this);
    detectionButton->setFixedSize(120, 40);
    detectionButton->setStyleSheet(
        "QPushButton {"
        "   background-color: #FF9800;"
        "   color: white;"
        "   border-radius: 5px;"
        "   font-size: 14px;"
        "}"
    );

    // 添加到控制面板
    controlLayout->addWidget(roleLabel);
    controlLayout->addWidget(playerRoleCombo);
    controlLayout->addSpacing(20);
    controlLayout->addWidget(aiLabel);
    controlLayout->addWidget(aiDifficultyCombo);
    controlLayout->addStretch();
    controlLayout->addWidget(regretButton);
    controlLayout->addWidget(resetButton);
    controlLayout->addWidget(detectionButton);

    mainLayout->addLayout(controlLayout);

    // 初始化棋子检测器
    chessDetector = new ChessDetector(this);
    chessDetector->startDetection(); // 确保检测器在运行
    chessDetector->setPlayerRole(static_cast<ROLE>(playerRoleCombo->currentData().toInt()));
    // 连接信号和槽
    connect(resetButton, &QPushButton::clicked, this, &MainWindow::onResetClicked);
    connect(regretButton, &QPushButton::clicked, qipan, &QiPan::regretMove);
    connect(qipan, &QiPan::gameStatusChanged, this, &MainWindow::updateGameStatus);
    connect(playerRoleCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &MainWindow::onPlayerRoleChanged);
    connect(aiDifficultyCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &MainWindow::onAIDifficultyChanged);
    connect(qipan, &QiPan::playerMoved, this, &MainWindow::onPlayerMoved);
    connect(qipan, &QiPan::computerMoved, this, &MainWindow::onComputerMoved);
    connect(detectionButton, &QPushButton::clicked, 
            this, &MainWindow::onOpenDetectionWindow);
    connect(chessDetector, &ChessDetector::detectionInfo,
            this, &MainWindow::handleDetectionInfo);
    connect(chessDetector, &ChessDetector::verificationResult,
            this, &MainWindow::handleVerificationResult);
    connect(chessDetector, &ChessDetector::pieceLocked,
            this, &MainWindow::handlePieceLocked);
    connect(servoController, &ServoController::receivedCommand,this, &MainWindow::handleServoCommand);
    connect(qipan, &QiPan::piecesRemoved, this, &MainWindow::handlePiecesRemoved);
  
    chessDetector->setPlayerRole(PLAYER); // 默认玩家先手
    // 连接角色变化信号
    connect(playerRoleCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, [this](int index) {
                ROLE role = static_cast<ROLE>(playerRoleCombo->itemData(index).toInt());
                chessDetector->setPlayerRole(role);
            });

    // 初始更新
    updateGameStatus();
}

MainWindow::~MainWindow()
{
    // 关闭串口连接
    if (motorController) {
        motorController->close();
    }
    if (servoController) {
        servoController->close();
    }
    
    // 关闭检测窗口
    if (detectionWindow) {
        detectionWindow->close();
        delete detectionWindow;
    }
}

// 棋盘坐标到电机坐标的转换函数
QPoint MainWindow::convertBoardCoordToMotor(int boardX, int boardY) {
    // 获取棋盘逻辑坐标对应的像素坐标
    cv::Point pixelPos = chessDetector->getPixelPositionForBoardCoord(boardX, boardY);
    
    if (pixelPos.x < 0 || pixelPos.y < 0) {
        qWarning() << "未找到棋盘格(" << boardX << "," << boardY << ")的像素坐标";
        return QPoint(0, 0);
    }
    
    qDebug() << "棋盘坐标(" << boardX << "," << boardY 
             << ") -> 像素坐标(" << pixelPos.x << "," << pixelPos.y << ")";
    
    // 使用像素坐标转换为电机坐标
    int motorX = 53.33*pixelPos.x - 7906;
    int motorY = 53.33*pixelPos.y + 2881;
    
    qDebug() << "转换后的电机坐标: (" << motorX << "," << motorY << ")";
    
    return QPoint(motorX, motorY);
}

void MainWindow::handlePieceLocked(const std::string& pieceName, int motorX, int motorY)
{
    qDebug() << "移动棋子:" << QString::fromStdString(pieceName)
             << "到电机坐标: (" << motorX << "," << motorY << ")";
    
    // 通过串口发送移动指令
    motorController->moveXY(motorX, motorY);
}

void MainWindow::updateGameStatus() {
    // 更新悔棋按钮状态
    regretButton->setEnabled(!qipan->isGameOver() && qipan->currentPlayer() == PLAYER);

    // 获取玩家选择的角色
    ROLE playerRole = static_cast<ROLE>(playerRoleCombo->currentData().toInt());
    
    // 确定棋子标记
    QString playerMark = (playerRole == PLAYER) ? "X (黑棋)" : "O (白棋)";
    QString computerMark = (playerRole == PLAYER) ? "O (白棋)" : "X (黑棋)";
    
    switch (qipan->gameState()) {
        case PLAYING:
            if (qipan->currentPlayer() == PLAYER) {
                statusLabel->setText("玩家回合 - " + playerMark);
            } else {
                statusLabel->setText("电脑思考中 - " + computerMark);
            }
            statusLabel->setStyleSheet("font-size: 24px; font-weight: bold; color: #333;");
            break;
        case PLAYER_WIN:
            statusLabel->setText("玩家获胜! - " + playerMark);
            statusLabel->setStyleSheet("font-size: 28px; font-weight: bold; color: #2196F3;");
            break;
        case COMPUTER_WIN:
            statusLabel->setText("电脑获胜! - " + computerMark);
            statusLabel->setStyleSheet("font-size: 28px; font-weight: bold; color: #F44336;");
            break;
        case DRAW:
            statusLabel->setText("平局!");
            statusLabel->setStyleSheet("font-size: 28px; font-weight: bold; color: #9C27B0;");
            break;
    }
}

void MainWindow::onResetClicked() {
    qipan->resetGame();
    
    // 游戏重置时，将机械臂移动到初始位置
    QTimer::singleShot(100, [this]() {
        motorController->moveXY(0, 0); // 移动到初始位置
    });
}

void MainWindow::onPlayerRoleChanged(int index) {
    ROLE role = static_cast<ROLE>(playerRoleCombo->itemData(index).toInt());
    qipan->setPlayerRole(role);
    updateGameStatus();
    
    // 重置游戏时设置正确的先手玩家
    if (role == PLAYER) {
        // 玩家选择先手(黑棋)
        qipan->setCurrentPlayer(PLAYER);
    } else {
        // 玩家选择后手(白棋)
        qipan->setCurrentPlayer(COMPUTER);
    }
}
void MainWindow::onAIDifficultyChanged(int index) {
    qipan->setAIDifficulty(index + 1);
}


void MainWindow::onPlayerMoved(int x, int y) {
    qDebug() << "玩家在棋盘位置 (" << x << "," << y << ") 落子";
    
    // 获取玩家选择的角色
    ROLE playerRole = static_cast<ROLE>(playerRoleCombo->currentData().toInt());
    
    // 确定玩家应该取什么颜色的棋子
    bool isPlayerBlack = (playerRole == PLAYER);
    QString servoCommand = isPlayerBlack ? "B" : "W";
    QPoint pickupPos = isPlayerBlack ? QPoint(26500, 10700) : QPoint(26500, 5200);
    
    // 将棋盘坐标转换为电机坐标
    QPoint motorPos = convertBoardCoordToMotor(x, y);
    
    // 移动到棋子拾取位置
    motorController->moveXY(pickupPos.x(), pickupPos.y());
    
    // 动作序列使用链式定时器确保顺序执行
    QTimer::singleShot(4000, this, [=]() {  // 等待移动到拾取位置
        motorController->moveZ(3100);  // 下降到取棋子位置
        QTimer::singleShot(500, this, [=]() {  // 等待下降完成
            servoController->DCT_on();  // 夹取棋子
            QTimer::singleShot(1000, this, [=]() {  // 等待夹取完成
                motorController->moveZ(0);  // 提升机械臂
                QTimer::singleShot(2000, this, [=]() {  // 等待提升完成
                    // 移动到目标位置
                    motorController->moveXY(motorPos.x(), motorPos.y());
                    QTimer::singleShot(3000, this, [=]() {  // 等待移动到目标位置
                        motorController->moveZ(3100);  // 下降到放置高度
                        QTimer::singleShot(2000, this, [=]() {  // 等待下降完成
                            servoController->DCT_off();  // 释放棋子
                            QTimer::singleShot(1000, this, [=]() {  // 等待释放完成
                                motorController->moveZ(0);  // 提升机械臂
                                QTimer::singleShot(2000, this, [=]() {  // 等待提升完成
                                    // 返回拾取位置
                                    motorController->moveXY(pickupPos.x(), pickupPos.y());
                                    QTimer::singleShot(5000, this, [=]() {
                                        // 等待2秒让棋子稳定
                                        QTimer::singleShot(2000, this, [=]() {
                                            // 启动验证
                                            chessDetector->startContinuousVerification(x, y, PLAYER);
                                            
                                            // 发送棋子放置完成的信号
                                            if (servoCommand == "B") {
                                                servoController->B_on();
                                            } else {
                                                servoController->W_on();
                                            }
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
    });
    
    // 设置游戏状态为等待验证
    qipan->setVerificationState(x, y, PLAYER);
}

void MainWindow::onComputerMoved(int x, int y) {
    qDebug() << "电脑在棋盘位置 (" << x << "," << y << ") 落子";
    
    // 获取玩家选择的角色
    ROLE playerRole = static_cast<ROLE>(playerRoleCombo->currentData().toInt());
    
    // 确定电脑应该取什么颜色的棋子
    bool isComputerBlack = (playerRole == COMPUTER);
    QString servoCommand = isComputerBlack ? "B" : "W";
    QPoint pickupPos = isComputerBlack ? QPoint(26500, 10700) : QPoint(26500, 5200);
    
    // 将棋盘坐标转换为电机坐标
    QPoint motorPos = convertBoardCoordToMotor(x, y);
    
    // 移动到棋子拾取位置
    motorController->moveXY(pickupPos.x(), pickupPos.y());
    
    // 动作序列使用链式定时器确保顺序执行
    QTimer::singleShot(4000, this, [=]() {  // 等待移动到拾取位置
        motorController->moveZ(3100);  // 下降到取棋子位置
        QTimer::singleShot(500, this, [=]() {  // 等待下降完成
            servoController->DCT_on();  // 夹取棋子
            QTimer::singleShot(1000, this, [=]() {  // 等待夹取完成
                motorController->moveZ(0);  // 提升机械臂
                QTimer::singleShot(2000, this, [=]() {  // 等待提升完成
                    // 移动到目标位置
                    motorController->moveXY(motorPos.x(), motorPos.y());
                    QTimer::singleShot(3000, this, [=]() {  // 等待移动到目标位置
                        motorController->moveZ(3100);  // 下降到放置高度
                        QTimer::singleShot(2000, this, [=]() {  // 等待下降完成
                            servoController->DCT_off();  // 释放棋子
                            QTimer::singleShot(2000, this, [=]() {  // 等待释放完成
                                motorController->moveZ(0);  // 提升机械臂
                                QTimer::singleShot(1000, this, [=]() {  // 等待提升完成
                                    // 返回拾取位置
                                    motorController->moveXY(pickupPos.x(), pickupPos.y());
                                    QTimer::singleShot(5000, this, [=]() {
                                        // 等待2秒让棋子稳定
                                        QTimer::singleShot(2000, this, [=]() {
                                            // 启动验证
                                            chessDetector->startContinuousVerification(x, y, COMPUTER);
                                            
                                            // 发送棋子放置完成的信号
                                           if (servoCommand == "B") {
                                                servoController->B_on();
                                            } else {
                                                servoController->W_on();
                                            }
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
    });
    
    // 设置游戏状态为等待验证
    qipan->setVerificationState(x, y, COMPUTER);
}


void MainWindow::onOpenDetectionWindow()
{
    if (!detectionWindow) {
        detectionWindow = new ChessDetectionWindow(this);
    }
    detectionWindow->show();
    detectionWindow->raise();
    detectionWindow->activateWindow();
}



void MainWindow::handleDetectionInfo(const QString &info)
{
    qDebug() << "检测信息:" << info;
}

void MainWindow::handleVerificationResult(int boardX, int boardY, bool success) {
    qDebug() << "收到验证结果: (" << boardX << "," << boardY << ") = " << success;

    // 将验证结果传递给棋盘
    qipan->handleVerificationResult(boardX, boardY, success);
    
    // 更新游戏状态显示
    updateGameStatus();
}


void MainWindow::handleServoCommand(quint8 state, quint8 row, quint8 col) {
    qDebug() << "Received servo command:"
             << "State:" << state
             << "Row:" << row
             << "Col:" << col;
    
    // 将物理棋盘坐标转换为逻辑棋盘坐标 (1-3 -> 0-2)
    int boardX = row - 1;
    int boardY = col - 1;
    
    // 检查坐标是否有效
    if (boardX < 0 || boardX > 2 || boardY < 0 || boardY > 2) {
        qWarning() << "Invalid board coordinates: (" << row << "," << col << ")";
        return;
    }
    
    // 获取玩家选择的角色
    ROLE playerRole = static_cast<ROLE>(playerRoleCombo->currentData().toInt());
    
    // 确定物理操作对应的游戏角色
    ROLE movedRole;
    if (state == 0) {
        // 物理白棋操作
        movedRole = (playerRole == PLAYER) ? COMPUTER : PLAYER;
    } else {
        // 物理黑棋操作
        movedRole = (playerRole == PLAYER) ? PLAYER : COMPUTER;
    }
    
    // 检查当前回合是否匹配
    if (qipan->currentPlayer() != movedRole) {
        qDebug() << "Not your turn. Current player:" << qipan->currentPlayer()
                 << "Moved role:" << movedRole;
        return;
    }
    
    // 检查位置是否为空
    if (qipan->isPositionOccupied(boardX, boardY)) {
        qDebug() << "Position (" << boardX << "," << boardY << ") is already occupied";
        return;
    }
    
    // 执行落子操作
    qDebug() << "Making move at (" << boardX << "," << boardY << ") for role:" << movedRole;
    qipan->makeMove(boardX, boardY, movedRole);
}
void MainWindow::handlePiecesRemoved(const QList<QPair<ROLE, QPoint>>& pieces) {
    const QPoint whiteTarget(0, 0);
    const QPoint blackTarget(0, 0);
    ROLE playerRole = static_cast<ROLE>(playerRoleCombo->currentData().toInt());
    
    for (const auto& piece : pieces) {
        ROLE role = piece.first;
        QPoint boardPos = piece.second;
        bool isBlack = (playerRole == PLAYER) ? (role == PLAYER) : (role == COMPUTER);
        QPoint motorPos = convertBoardCoordToMotor(boardPos.x(), boardPos.y());
        QPoint target = isBlack ? blackTarget : whiteTarget;
        
        moveQueue.append(qMakePair(motorPos, target));
    }
    
    // 如果没有正在移动的操作，开始处理队列
    if (!isMoving && !moveQueue.isEmpty()) {
        processNextMove();
    }
}

void MainWindow::movePieceToTarget(const QPoint& from, const QPoint& to, bool isBlack) {
    motorController->moveXY(from.x(), from.y());  // 移动到棋子位置

    QTimer::singleShot(4000, this, [=]() {  // 等待移动到拾取位置
        motorController->moveZ(3100);  // 下降到取棋子位置

        QTimer::singleShot(500, this, [=]() {  // 等待下降完成
            servoController->DCT_on();  // 夹取棋子

            QTimer::singleShot(1000, this, [=]() {  // 等待夹取完成
                motorController->moveZ(0);  // 提升机械臂

                QTimer::singleShot(2000, this, [=]() {  // 等待提升完成
                    motorController->moveXY(to.x(), to.y());  // 移动到目标位置

                    QTimer::singleShot(3000, this, [=]() {  // 等待移动到目标位置
                        motorController->moveZ(3100);  // 下降到放置高度

                        QTimer::singleShot(2000, this, [=]() {  // 等待下降完成
                            servoController->DCT_off();  // 释放棋子

                            QTimer::singleShot(2000, this, [=]() {  // 等待释放完成
                                motorController->moveZ(0);  // 提升机械臂

                                QTimer::singleShot(1000, this, [=]() {  // 等待提升完成
                                    motorController->moveXY(0, 0);  // 返回拾取位置
                                });
                            });
                        });
                    });
                });
            });
        });
    });
}
void MainWindow::processNextMove() {
    if (moveQueue.isEmpty()) {
        isMoving = false;
        return;
    }
    
    isMoving = true;
    auto move = moveQueue.takeFirst();
    QPoint from = move.first;
    QPoint to = move.second;
    bool isBlack = true; 
    

    motorController->moveXY(from.x(), from.y());
    
    QTimer::singleShot(4000, this, [=]() {
        motorController->moveZ(3100);
        
        QTimer::singleShot(500, this, [=]() {
            servoController->DCT_on();
            
            QTimer::singleShot(1000, this, [=]() {
                motorController->moveZ(0);
                
                QTimer::singleShot(2000, this, [=]() {
                    motorController->moveXY(to.x(), to.y());
                    
                    QTimer::singleShot(3000, this, [=]() {
                        motorController->moveZ(3100);
                        
                        QTimer::singleShot(2000, this, [=]() {
                            servoController->DCT_off();
                            
                            QTimer::singleShot(2000, this, [=]() {
                                motorController->moveZ(0);
                                
                                QTimer::singleShot(1000, this, [=]() {
                                    motorController->moveXY(0, 0);
                                    
                                    QTimer::singleShot(3000, this, [=]() {
                                        // 当前棋子移动完成，处理下一个
                                        processNextMove();
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
    });
}
